package comps

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/antchfx/xquery/xml"
	"github.com/astaxie/beego/logs"
)

var (
	Resources    map[string]interface{} //资源定义
	Components   map[string]interface{} //控件定义
	ComponentUis map[string]interface{} //控件UI定义
)

func init() {
	l := logs.GetLogger()
	//资源定义
	Resources = make(map[string]interface{})
	//控件定义
	Components = make(map[string]interface{})
	//控件UI定义
	ComponentUis = make(map[string]interface{})
	files, err := WalkDir("./plugins", ".xml")
	if err == nil {
		for _, f := range files {
			l.Println("loading definitions:", f)
			content, err1 := ioutil.ReadFile(f)
			if err1 == nil {
				root, err1 := xmlquery.Parse(strings.NewReader(string(content)))

				if err1 == nil {

					/*扫描资源定义*/
					xmlquery.FindEach(root, "//resource", func(i int, node *xmlquery.Node) {

						resource := make(map[string]interface{})

						//resource attrs
						for _, attr := range node.Attr {
							resource[attr.Name.Local] = attr.Value
						}

						//resource settings
						settings := make([]map[string]interface{}, 1)
						xmlquery.FindEach(node, "//setting", func(k int, settingNode *xmlquery.Node) {

							setting := make(map[string]interface{})

							for _, attr := range settingNode.Attr {
								setting[attr.Name.Local] = attr.Value
							}
							nameNode := settingNode.SelectElement("name")

							if nameNode != nil {
								setting["name"] = nameNode.InnerText()
							}

							defaultValueNode := settingNode.SelectElement("defaultValue")
							if defaultValueNode != nil {
								setting["defaultValue"] = defaultValueNode.InnerText()
							}

							choicesNode := settingNode.SelectElement("choices")
							if choicesNode != nil {
								choicesList := make([]string, 1)
								for _, c := range choicesNode.SelectElements("choice") {
									choicesList = append(choicesList, c.InnerText())
								}
								setting["choices"] = choicesList
							}

							settings = append(settings, setting)
						})
						resource["settings"] = settings
						Resources[(resource["id"]).(string)] = resource

					})
					/*扫描控件定义*/

					xmlquery.FindEach(root, "//component", func(i int, node *xmlquery.Node) {

						component := make(map[string]interface{})

						//resource attrs
						for _, attr := range node.Attr {
							component[attr.Name.Local] = attr.Value
						}

						//resource settings
						settings := make([]map[string]interface{}, 1)
						xmlquery.FindEach(node, "//setting", func(k int, settingNode *xmlquery.Node) {

							setting := make(map[string]interface{})

							for _, attr := range settingNode.Attr {
								setting[attr.Name.Local] = attr.Value
							}
							nameNode := settingNode.SelectElement("name")

							if nameNode != nil {
								setting["name"] = nameNode.InnerText()
							}

							defaultValueNode := settingNode.SelectElement("defaultValue")
							if defaultValueNode != nil {
								setting["defaultValue"] = defaultValueNode.InnerText()
							}

							choicesNode := settingNode.SelectElement("choices")
							if choicesNode != nil {
								choicesList := make([]string, 1)
								for _, c := range choicesNode.SelectElements("choice") {
									choicesList = append(choicesList, c.InnerText())
								}
								setting["choices"] = choicesList
							}

							settings = append(settings, setting)
						})
						component["settings"] = settings

						xmlquery.FindEach(node, "//name", func(k int, child *xmlquery.Node) {
							if k == 0 {
								component["name"] = child.InnerText()
							}
						})
						xmlquery.FindEach(node, "//className", func(k int, child *xmlquery.Node) {
							if k == 0 {
								component["className"] = child.InnerText()
							}
						})
						xmlquery.FindEach(node, "//keywords", func(k int, child *xmlquery.Node) {
							if k == 0 {
								component["keywords"] = child.InnerText()
							}
						})
						xmlquery.FindEach(node, "//description", func(k int, child *xmlquery.Node) {
							if k == 0 {
								component["description"] = child.InnerText()
							}
						})
						//component["name"] = xmlquery.FindOne(node, "//name").InnerText()
						//component["className"] = xmlquery.FindOne(node, "//className").InnerText()
						//component["keywords"] = xmlquery.FindOne(node, "//keywords").InnerText()
						//component["description"] = xmlquery.FindOne(node, "//description").InnerText()

						Components[(component["id"]).(string)] = component

					})

					/*扫描控件UI设置*/
					xmlquery.FindEach(root, "//component-ui", func(i int, node *xmlquery.Node) {
						ui := make(map[string]interface{})
						//resource attrs
						for _, attr := range node.Attr {
							ui[attr.Name.Local] = attr.Value
						}
						iconImageNode := xmlquery.FindOne(node, "//iconImage")
						ui["iconImage"] = iconImageNode.InnerText()
						ui["name"] = (Components[ui["componentId"].(string)].(map[string]interface{}))["name"]

						ComponentUis[ui["componentId"].(string)] = ui
					})
				} else {
					fmt.Println(err1)
				}

			}
		}
	}

	//fmt.Println(Resources)
}

//获取指定目录及所有子目录下的所有文件，可以匹配后缀过滤。
func WalkDir(dirPth, suffix string) (files []string, err error) {
	files = make([]string, 0, 30)
	suffix = strings.ToUpper(suffix) //忽略后缀匹配的大小写

	err = filepath.Walk(dirPth, func(filename string, fi os.FileInfo, err error) error { //遍历目录
		//if err != nil { //忽略错误
		// return err
		//}

		if fi.IsDir() { // 忽略目录
			return nil
		}

		if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) {
			files = append(files, filename)
		}

		return nil
	})

	return files, err
}
